package com.deepwiki.service;

import com.deepwiki.config.WikiConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 提示词服务 - 对应原项目的PromptContext
 */
@Service
public class PromptService {

    private static final Logger logger = LoggerFactory.getLogger(PromptService.class);

    private final String promptPath;
    private final Map<String, String> promptCache = new ConcurrentHashMap<>();

    @Autowired
    public PromptService(WikiConfig wikiConfig) {
        this.promptPath = wikiConfig.getPromptTemplatesDirectory();
        // 确保提示词目录存在
        try {
            Files.createDirectories(Paths.get(promptPath));
        } catch (IOException e) {
            logger.error("创建提示词目录失败: {}", promptPath, e);
        }
    }

    /**
     * 获取仓库相关的提示词
     *
     * @param name 提示词名称
     * @param args 参数映射
     * @param model 模型名称（可选）
     * @return 处理后的提示词
     */
    public String getWarehousePrompt(String name, Map<String, Object> args, String model) {
        return getPrompt("Warehouse", name, args, model);
    }

    /**
     * 获取聊天相关的提示词
     *
     * @param name 提示词名称
     * @param args 参数映射
     * @param model 模型名称（可选）
     * @return 处理后的提示词
     */
    public String getChatPrompt(String name, Map<String, Object> args, String model) {
        return getPrompt("Chat", name, args, model);
    }

    /**
     * 通用提示词获取方法
     *
     * @param category 提示词分类
     * @param name 提示词名称
     * @param args 参数映射
     * @param model 模型名称（可选）
     * @return 处理后的提示词
     */
    public String getPrompt(String category, String name, Map<String, Object> args, String model) {
        try {
            String fileName = name + ".md";
            
            // 尝试加载模型特定版本的提示词
            if (model != null && !model.trim().isEmpty()) {
                String modelFileName = model + "_" + fileName;
                Path modelFilePath = Paths.get(promptPath, category, modelFileName);
                
                if (Files.exists(modelFilePath)) {
                    fileName = modelFileName;
                } else {
                    logger.warn("模型特定提示词文件不存在: {}, 使用默认版本: {}", modelFileName, fileName);
                }
            }
            
            // 加载提示词内容
            String promptContent = loadPromptFile(category, fileName);
            
            // 替换参数
            return replaceParameters(promptContent, args);
            
        } catch (Exception e) {
            logger.error("获取提示词失败: category={}, name={}, model={}", category, name, model, e);
            throw new RuntimeException("获取提示词失败: " + e.getMessage(), e);
        }
    }

    /**
     * 加载提示词文件
     */
    private String loadPromptFile(String category, String fileName) throws IOException {
        String cacheKey = category + "/" + fileName;
        
        // 检查缓存
        if (promptCache.containsKey(cacheKey)) {
            return promptCache.get(cacheKey);
        }
        
        Path filePath = Paths.get(promptPath, category, fileName);
        
        if (!Files.exists(filePath)) {
            throw new IllegalArgumentException("提示词文件不存在: " + filePath);
        }
        
        String content = Files.readString(filePath, StandardCharsets.UTF_8);
        
        // 缓存内容
        promptCache.put(cacheKey, content);
        
        logger.debug("加载提示词文件: {}", cacheKey);
        return content;
    }

    /**
     * 替换提示词中的参数
     */
    private String replaceParameters(String promptContent, Map<String, Object> args) {
        if (args == null || args.isEmpty()) {
            return promptContent;
        }
        
        String result = promptContent;
        
        for (Map.Entry<String, Object> entry : args.entrySet()) {
            String placeholder = "{{$" + entry.getKey() + "}}";
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            result = result.replace(placeholder, value);
        }
        
        return result;
    }

    /**
     * 清除提示词缓存
     */
    public void clearCache() {
        promptCache.clear();
        logger.info("提示词缓存已清除");
    }

    /**
     * 检查提示词文件是否存在
     */
    public boolean promptExists(String category, String name, String model) {
        try {
            String fileName = name + ".md";
            
            if (model != null && !model.trim().isEmpty()) {
                String modelFileName = model + "_" + fileName;
                Path modelFilePath = Paths.get(promptPath, category, modelFileName);
                if (Files.exists(modelFilePath)) {
                    return true;
                }
            }
            
            Path filePath = Paths.get(promptPath, category, fileName);
            return Files.exists(filePath);
            
        } catch (Exception e) {
            logger.error("检查提示词文件存在性失败: category={}, name={}, model={}", category, name, model, e);
            return false;
        }
    }

    /**
     * 获取README生成提示词
     */
    public String getReadmeGenerationPrompt(Map<String, Object> args, String model) {
        return getPrompt("Warehouse", "GenerateReadme", args, model);
    }

    /**
     * 获取目录树优化提示词
     */
    public String getDirectoryTreeOptimizationPrompt(Map<String, Object> args, String model) {
        return getPrompt("Warehouse", "OptimizeDirectoryTree", args, model);
    }

    /**
     * 获取分析目录结构提示词
     */
    public String getAnalyzeCataloguePrompt(Map<String, Object> args, String model) {
        return getPrompt("Warehouse", "AnalyzeCatalogue", args, model);
    }

    /**
     * 获取生成文档提示词
     */
    public String getGenerateDocsPrompt(String projectType, Map<String, Object> args, String model) {
        // 根据项目类型选择合适的提示词
        String promptName = switch (projectType.toLowerCase()) {
            case "cli", "tool" -> "GenerateDocsCLI";
            case "library", "framework" -> "GenerateDocsLibrary";
            case "web", "api" -> "GenerateDocsWeb";
            case "devops", "config" -> "GenerateDocsDevOps";
            default -> "GenerateDocs";
        };
        return getPrompt("Warehouse", promptName, args, model);
    }

    /**
     * 获取概览文档提示词
     */
    public String getOverviewPrompt(String projectType, Map<String, Object> args, String model) {
        // 根据项目类型选择合适的概览提示词
        String promptName = switch (projectType.toLowerCase()) {
            case "cli", "tool" -> "OverviewCLITools";
            case "devops", "config" -> "OverviewDocumentation";
            default -> "Overview";
        };
        return getPrompt("Warehouse", promptName, args, model);
    }
} 